package com.eurasia.assignment.service;

import java.util.List;
import java.util.stream.Collectors;

import com.eurasia.assignment.service.exception.ClassInfoNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eurasia.assignment.controller.dto.ClassSearchRequest;
import com.eurasia.assignment.controller.dto.CreateClassRequest;
import com.eurasia.assignment.controller.dto.UpdateClassRequest;
import com.eurasia.assignment.domain.Class;
import com.eurasia.assignment.infrastructure.entity.ClassEntity;
import com.eurasia.assignment.infrastructure.repository.ClassRepository;
import com.eurasia.assignment.infrastructure.specification.ClassSpecification;

/**
 * 班级服务类
 * 提供班级相关的业务逻辑
 */
@Service
public class ClassService {

    private final ClassRepository classRepository;
    private static final Logger log = LoggerFactory.getLogger(ClassService.class);

    @Autowired
    public ClassService(ClassRepository classRepository) {
        this.classRepository = classRepository;
    }


    @Transactional//事务注解，保证操作的原子性
    public Class createClass(CreateClassRequest request) {
        Class classObj = Class.create(
            request.getClassName(),
            request.getGrade(),
            request.getMajor(),
            request.getTutor(),
            request.getStudentCount(),
            request.getRemark()
        );
        
        var savedClass = classRepository.save(ClassEntity.fromDomain(classObj));

        return savedClass.toDomain();
    }


    /**
     * 更新班级信息
     * @param id 班级ID
     * @param request 更新请求
     * @return 更新后的班级对象
     */
    @Transactional
    public Class updateClass(Long id, UpdateClassRequest request) {
        // 检查班级是否存在
        ClassEntity existingClass = classRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("班级不存在，ID: " + id));
        
        // 如果班级名称已更改，检查新名称是否与其他班级冲突
        if (!existingClass.getClassName().equals(request.getClassName()) && 
            classRepository.existsByClassNameAndIdNot(request.getClassName(), id)) {
            throw new IllegalArgumentException("班级名称已存在: " + request.getClassName());
        }
        
        // 创建领域对象并更新
        Class classObj = existingClass.toDomain();
        classObj.update(
            request.getClassName(),
            request.getGrade(),
            request.getMajor(),
            request.getTutor(),
            request.getStudentCount(),
            request.getRemark()
        );
        
        // 保存更新后的实体
        ClassEntity updatedEntity = ClassEntity.fromDomain(classObj);
        return classRepository.save(updatedEntity).toDomain();
    }

    /**
     * 更新班级信息并自动保存
     */
    @Transactional
    public void updateClass(Long id, String className, String grade, String major, 
                           String tutor, Integer studentCount, String remark) {
        classRepository.findById(id).ifPresentOrElse(existingClass -> {
            // 获取领域对象
            Class classObj = existingClass.toDomain();
            
            // 更新领域对象
            classObj.update(className, grade, major, tutor, studentCount, remark);
            
            // 保存更新后的实体
            ClassEntity updatedEntity = ClassEntity.fromDomain(classObj);
            classRepository.save(updatedEntity);
        }, () -> {
            throw new RuntimeException("班级不存在，ID: " + id);
        });
    }

    /**
     * 根据ID获取班级
     */
    public Class getClassById(Long id) {
        return classRepository.findById(id).map(ClassEntity::toDomain).orElseThrow(
                ()->new ClassInfoNotFoundException(id.toString())
        );
    }

    /**
     * 获取所有班级
     */
    public List<Class> getAllClasses() {
        return classRepository.findAll().stream().map(ClassEntity::toDomain).collect(Collectors.toList());
    }

    /**
     * 分页查询班级信息
     * @param searchRequest 搜索条件
     * @return 分页班级信息
     */
    public Page<Class> searchClasses(ClassSearchRequest searchRequest) {
        // 设置默认分页参数
        int page = searchRequest.getPage() != null ? searchRequest.getPage() : 0;
        int size = searchRequest.getSize() != null ? searchRequest.getSize() : 10;
        
        // 设置排序
        Sort sort = Sort.unsorted();
        if (searchRequest.getSortBy() != null && !searchRequest.getSortBy().isEmpty()) {
            Direction direction = "desc".equalsIgnoreCase(searchRequest.getSortDirection()) 
                ? Direction.DESC : Direction.ASC;
            sort = Sort.by(direction, searchRequest.getSortBy());
        }
        
        // 创建分页对象
        Pageable pageable = PageRequest.of(page, size, sort);
        
        // 构建查询规格
        Specification<ClassEntity> spec = ClassSpecification.buildSpecification(searchRequest);
        
        log.debug("执行分页查询: page={}, size={}, sortBy={}, direction={}", 
                page, size, searchRequest.getSortBy(), searchRequest.getSortDirection());
        
        // 执行查询并转换结果
        Page<Class> result = classRepository.findAll(spec, pageable)
                .map(ClassEntity::toDomain);
        
        log.debug("查询结果: 总条数={}, 当前页记录数={}", 
                result.getTotalElements(), result.getContent().size());
        
        return result;
    }

    /**
     * 删除班级信息
     * @param id 班级ID
     * @throws RuntimeException 班级不存在时抛出
     */
    @Transactional
    public void deleteClass(Long id) {
        if (!classRepository.existsById(id)) {
            throw new RuntimeException("班级不存在，ID: " + id);
        }
        classRepository.deleteById(id);
        log.debug("班级已删除，ID: {}", id);
    }
} 